home *** CD-ROM | disk | FTP | other *** search
/ Mac Power 1999 June / macpower199906.bin / 9906⁄AMUG / INTERNET / NetCacheResolver 0.9d7.sit / NetCacheResolver 0.9d7 folder / source code CWPro4 / source / NCR_Resolve.c < prev    next >
Encoding:
Text File  |  1999-02-04  |  14.7 KB  |  467 lines  |  [TEXT/CWIE]

  1. // NetCache Resolver, 1995-96 (C) Mizutori Tetsuya
  2. // - NCR_Resolve.c, October 8, 1995, May 12 1996
  3. // Modified: February 2, 1999. (workaround for new format of cache database)
  4. // This document is pretty printed in 10-point Geneva font.
  5.  
  6. //#define DEBUG 1
  7.  
  8. #include "NCR_Basic.h"
  9. #include "NCR_Resolve.h"
  10. #include "NCR_File.h"
  11. #include "NCR_Error.h"
  12. #ifdef DEBUG
  13. #include "NCR_Message.h"
  14. #endif /*DEBUG */
  15.  
  16. // definition
  17. // in Header
  18. #define    OFFS_BLOCKSIZE    0x00000C
  19. #define    OFFS_NUMBPAIRS    0x000038
  20.  
  21. // start with pURL
  22. #define    OFFS_URL_STR        4
  23.  
  24. // start with pFInfo
  25. #define    OFFS_CACHE_INFO    4
  26. #define    WIDTH_CACHE_INFO    25    // 5*sizeof(long) + 1 + sizeof(long)
  27. #define    OFFS_DATE1        OFFS_CACHE_INFO + 4
  28. #define    OFFS_DATE2        OFFS_CACHE_INFO + 8
  29. #define    OFFS_FILESIZE        OFFS_CACHE_INFO + 16
  30. #define    OFFS_CACHE_STR    OFFS_CACHE_INFO + WIDTH_CACHE_INFO
  31.  
  32. #define    OFFS_DOC_INFO        OFFS_CACHE_STR + 4 /* +#(OFFS_CACHE_STR) */
  33. //#define    WIDTH_DOC_INFO    29        // October 8, 1995; char[1]+long[7]
  34.     #define    WIDTH_DOC_INFO    17    // May 12, 1996; char[1]+long[4]
  35. #define    OFFS_DOC_COUNT    OFFS_DOC_INFO + WIDTH_DOC_INFO + 4    // +char[1]+long[5]
  36.     #define    OFFS_EXPORT_STR    OFFS_DOC_INFO + WIDTH_DOC_INFO
  37.     #define    OFFS_EXDATA_STR    OFFS_EXPORT_STR + 4/* +#(OFFS_EXPORT_STR) */
  38. // #define    OFFS_FORM_STR    OFFS_DOC_INFO + WIDTH_DOC_INFO    // October 8, 1995
  39. #define    OFFS_FORM_STR    OFFS_DOC_INFO+ 4/* +#(OFFS_EXPORT_STR) */ + 4/* +#(OFFS_EXDATA_STR) */
  40. #define    OFFS_TYPE_STR        OFFS_FORM_STR + 4 /* +#(OFFS_FORM_STR) */
  41.  
  42. typedef struct {    // If len is zero, then no allocation space for str[] is occupied.
  43.     unsigned long    len;        // length of string, including the terminator '¥0'
  44.     unsigned char    str[];    // character string, teminated by '¥0'
  45. } QString;        // size of QString is at least 4 bytes, which is the case that len is zero.
  46.  
  47. typedef struct {    // length of DummyData record must be determined dynamically
  48.     unsigned char    dumchar;    // the first filler character
  49.     unsigned char    dumstr[];
  50. } DummyData;
  51.  
  52. typedef struct {
  53.     unsigned long    size;        // total size occupied by this record, in bytes
  54.     QString        url;        // e.g. "http://www.a.b.c/index.html"
  55.     unsigned long    _end;        // ? = 0x0000 (terminator ?)
  56. } _URL_Record;
  57.  
  58.  
  59. typedef struct {
  60.     unsigned long    size;        // total size occupied by this record, in bytes
  61. // OFFS_CACHE_INFO
  62.     unsigned long    semaphore;    // ? = 0x0003 (for NN3), = 0x0005 (for NEW FORMAT).
  63.     unsigned long    date1;    // time stamp 1 (creation ?)
  64.     unsigned long    date2;    // time stamp 2 (modification ?)
  65.     unsigned long    _2;        // ? = 0x0000
  66.     unsigned long    filesize;    // cache file size, in bytes
  67.     unsigned char    _3;        // ? = 0x00, odd byte!
  68.     unsigned long    _4;        // ? = 0x0000 (count-1 for strings followed ?)
  69. // OFFS_CACHE_STR
  70.     QString        cache;    // e.g. "cache123000.html"
  71. // OFFS_DOC_INFO
  72. /***** October 8, 1995 *****
  73.     unsigned long    _5[6];    // ? = {0,1,0,0,0,0}
  74.     unsigned char    _6;        // ? = 0x00, odd byte!
  75.     unsigned long    _7;        // ? = 0x0000 or 0x0001 (count-1 for strings followed ?)
  76. *****/
  77. /***** May 12, 1995 *****/
  78.     unsigned long    _5;        // ? = 0x0000
  79.     unsigned char    _6;        // ? = 0x01, odd byte!
  80.     unsigned long    _51;        // ? = 0x0000 or 0x0002
  81.     unsigned long    _52;        // ? = 0x0000 or 0x0008
  82.     unsigned long    _53;        // ? = 0x0000 or 0x0028
  83.     // OFFS_EXPORT_STR        // Following 3 fields (export, exdata, _7) are missing in new format.
  84.     QString        export;    // e.g. "RC4-Export" (* MISSING *)
  85.     // OFFS_EXDATA_STR
  86.     QString        exdata;    // e.g. "???Data Export Inc. v.1.0..." (*MISSING *)
  87.     unsigned long    _7;        // ? = 0x0000 or 0x0001 (count-1 for strings followed ?) (* MISSING *)
  88. // OFFS_FORM_STR
  89.     QString        form;    // e.g. "Content-type: application..."
  90. // OFFS_TYPE_STR
  91.     QString        type;        // e.g. "text/html"
  92.     unsigned char    _8[9];    // ? = {all 0x00's}, odd bytes!
  93.     unsigned long    fsize;        // cache file size, in bytes (same value to .filesize)
  94.     DummyData    _9;        // ? = filled by 0x00's, even or odd bytes!
  95.     unsigned long    _end;        // ? = 0x0000 (terminator ?)
  96. } _FInfo_Record;
  97.  
  98.  
  99. typedef struct {
  100.     unsigned long    url;
  101.     unsigned long    cache;
  102.     unsigned long    form;
  103.     unsigned long    type;
  104.     unsigned long    sizeurl;
  105.     unsigned long    sizecache;
  106.     unsigned long    sizeform;
  107.     unsigned long    sizetype;
  108.     unsigned long    filesize;
  109.     unsigned long    date1, date2;
  110. } IndexTableRecord, *IndexTablePtr, **IndexTableHandle;
  111.  
  112. // prototype
  113. static unsigned long GetLongLH (unsigned char *p );
  114.  
  115. static OSErr SetupHeader ( Handle theHndl );
  116. static OSErr DoHandleCacheData ( Handle theHndlData, Handle theHndl );
  117. static OSErr MakeRecord ( Handle theHndl, unsigned long startOffset, long index, IndexTableRecord *table );
  118. static OSErr PrintRecord ( Handle theHndl, long index, IndexTableRecord *table );
  119. static OSErr InsertRecord ( Handle theHndl, Handle theHndl2, long index, IndexTableRecord *table );
  120. static OSErr InsertHeader ( Handle theHndl, Handle theHndl2 );
  121. static OSErr AppendString ( Handle theHndl, const char *str, Size length );
  122.  
  123. /***** General functions *****/
  124.  
  125. #define GetWordHL(p) ( (unsigned short) * ( (unsigned short *) (p) ) )
  126. #define GetLongHL(p) ( (unsigned long) * ( (unsigned long *) (p) ) )
  127.  
  128. static unsigned long GetLongLH (unsigned char *p )
  129. {
  130.     unsigned long    n = 0;
  131.     unsigned char    *q;
  132.     
  133.     q = (unsigned char *) &n;
  134.     
  135.     q[0] = p[3];
  136.     q[1] = p[2];
  137.     q[2] = p[1];
  138.     q[3] = p[0];
  139.     
  140.     return n;
  141. }
  142.  
  143. /***** Read Database from the file *****/
  144. OSErr GetRecordFromFile ( FSSpec *theFSSpec, FInfo *theFInfo, Handle theHndl, long *count )
  145. {
  146.     Handle        theHndlData = nil;
  147.     long            datasize;
  148.     OSType        fdType = 'DBMC';        // read from 'STR#'
  149.     Str31        strFdType;
  150.     OSErr        err = noErr;
  151.     
  152.     // read database from the file
  153.     GetIndString( strFdType, STRID_CACHE, STRIX_CCACHETYPE );
  154.     BlockMove( &strFdType[1], &fdType, 4 );
  155.  
  156.     err = FSpGetFInfo( theFSSpec, theFInfo );
  157.     if ( err != noErr ) { ErrorMessageFS( err, false ); goto out; }
  158.  
  159.     if ( theFInfo->fdType != fdType ) {
  160.         err = errAEWrongDataType;
  161.         ErrorMessageAE( err, false ); goto out; }
  162.  
  163.     theHndlData = NewHandleClear( 0 );            // create a Handle 'theHndlData'
  164.     if ( (err=MemError()) != noErr ) { ErrorMessageMEM( err, true ); }
  165.  
  166.     err = ReadFile( theFSSpec, theFInfo, theHndlData, &datasize );
  167.     if ( err != noErr ) { ErrorMessageFS( err, false ); goto out; }
  168.     
  169.     // convert 'theHndlData' to 'theHndl'
  170.     err = DoHandleCacheData( theHndlData, theHndl );
  171.     *count = GetHandleSize( theHndl );
  172.  
  173.   out:
  174.       if ( theHndlData != nil ) DisposeHandle( theHndlData );    // dispose the Handle 'theHndlData'
  175.       
  176.     return err;
  177. }
  178.  
  179.  
  180. /***** do Handle Data *****/
  181. // globals
  182. unsigned long    gHndlSize = 0;            // set by GetHandleSize()
  183. unsigned long    gBlockSize = 0x004000;    // read from at the offset 'OFFS_BLOCKSIZE'
  184.  
  185. static OSErr SetupHeader ( Handle theHndl )
  186. {
  187.     if ( gHndlSize != 0 ) return noErr;
  188.  
  189.     gHndlSize = GetHandleSize( theHndl );
  190.     gBlockSize = GetLongHL((unsigned char *)*theHndl+OFFS_BLOCKSIZE );
  191.  
  192.     return noErr;
  193. }
  194.  
  195.  
  196. static OSErr DoHandleCacheData ( Handle theHndlData, Handle theHndl )
  197. {
  198.     IndexTableRecord    table;
  199.     unsigned long        n, index;
  200.     unsigned long        startOffset;
  201.     OSErr            err;
  202.  
  203. #ifdef DEBUG
  204.     Message("DoHandleData() start¥n");
  205. #endif /* DEBUG */
  206.  
  207.     SetupHeader( theHndlData );
  208.     
  209.     InsertHeader( theHndlData, theHndl );
  210.     
  211.     n = 0;
  212.     startOffset = gBlockSize;
  213.     while ( startOffset < gHndlSize ) {
  214.         for ( index=1; ; index++) {
  215.             err = MakeRecord( theHndlData, startOffset, index, &table );
  216. #ifdef DEBUG
  217.     Message("[%ld] startOffset=$%04X err=%d¥n", index, startOffset, err);
  218. #endif /* DEBUG */
  219.             if ( err == nilHandleErr ) break;
  220.             if ( err != noErr ) continue;
  221.         //    PrintRecord( theHndlData, n, &table );
  222.             InsertRecord( theHndlData, theHndl, n, &table );
  223.             n++;
  224.         }
  225.         startOffset += gBlockSize;
  226.     }
  227.     
  228. #ifdef DEBUG
  229.     Message("DoHandleData() end¥n");
  230. #endif /* DEBUG */
  231.     return noErr;
  232. }
  233.  
  234. /***** Make Record *****/
  235. #define ALLOWANCE_TOC        4096
  236. #define ALLOWANCE_LENGH        255
  237.  
  238. // index should begin with 1, not 0
  239. static OSErr MakeRecord ( Handle theHndl, unsigned long startOffset, long index, IndexTableRecord *table )
  240. {
  241.     long            count;
  242.     long            offsetURL, offsetFInfo;
  243.     unsigned char    *pHeap, *pHashTable, *pURL, *pFInfo;
  244.     long            sizeURL, sizeCache, sizeForm, sizeType;
  245.     unsigned char    *strURL, *strCache, *strForm, *strType;
  246.     unsigned long    filesize, date1, date2;
  247.     unsigned long    exportsize, exdatasize;
  248.     unsigned long    semaphore;        // for new format. February 2, 1999.
  249.     OSErr        err = noErr;
  250.     
  251.     HLock( theHndl );
  252.     
  253.     pHeap = (unsigned char *) *theHndl;
  254.     pHashTable = (unsigned char *) *theHndl + startOffset;
  255.     count = GetWordHL(pHashTable);
  256.     if ( count <= 0 || ALLOWANCE_TOC <= count ) { err = nilHandleErr; goto out; }
  257.     
  258.     count /= 2;
  259.     if ( index < 1 || count < index ) { err = nilHandleErr; goto out; }
  260.     index -= 1;
  261.     
  262.     // for URL
  263. //    offsetURL = GetWordHL( pHashTable + 4*index+2 );
  264.     pURL = pHashTable + GetWordHL( pHashTable + 4*index+2 );
  265.     
  266. //#define    OFFS_URL_STR        4
  267.     offsetURL = OFFS_URL_STR;
  268.     sizeURL = GetLongLH(pURL+offsetURL);
  269.     strURL = (unsigned char *) (pURL+offsetURL+sizeof(long));
  270. #ifdef DEBUG
  271.     Message("strURL: size=%ld¥n", sizeURL);
  272. #endif /* DEBUG */
  273.     if ( sizeURL <= 0 || ALLOWANCE_LENGH < sizeURL ) { err = paramErr; goto out; }
  274.     offsetURL += sizeof(long) + sizeURL;
  275.  
  276.  
  277.     // for File Info
  278.     pFInfo = pHashTable + GetWordHL( pHashTable + 4*index+4 );
  279.  
  280. //    For NN4 format.
  281.     semaphore = GetLongLH(pFInfo + 4);    // '3' for NN3, '5' for NN4. (?)
  282.  
  283. //#define    OFFS_CACHE_INFO    4
  284. //#define    WIDTH_CACHE_INFO    25
  285. //#define    OFFS_CACHE_STR    OFFS_CACHE_INFO + WIDTH_CACHE_INFO
  286.     offsetFInfo = OFFS_CACHE_STR;
  287.     
  288.     // cache filename
  289.     sizeCache = GetLongLH(pFInfo+offsetFInfo);
  290.     strCache = (unsigned char *) (pFInfo+offsetFInfo+sizeof(long));
  291. #ifdef DEBUG
  292.     Message("strCache: size=%ld¥n", sizeCache);
  293. #endif /* DEBUG */
  294.     if ( sizeCache <= 0 || ALLOWANCE_LENGH < sizeCache )  { err = paramErr; goto out; }
  295.     offsetFInfo += sizeof(long) + sizeCache;
  296.  
  297. #ifdef COMMENT // October 8, 1995
  298. //#define    OFFS_DOC_INFO        OFFS_CACHE_STR + 4 /* +#(OFFS_CACHE_STR) */
  299. //#define    WIDTH_DOC_INFO    29    // char[1]+long[7]
  300. //#define    OFFS_FORM_STR    OFFS_DOC_INFO + WIDTH_DOC_INFO
  301. //#define    OFFS_TYPE_STR        OFFS_FORM_STR + 4 /* +#(OFFS_FORM_STR) */
  302.     offsetFInfo += WIDTH_DOC_INFO;
  303. #endif // COMMENT
  304.  
  305. // May 12, 1996
  306. //#define    OFFS_DOC_INFO        OFFS_CACHE_STR + 4 /* +#(OFFS_CACHE_STR) */
  307. //#define    WIDTH_DOC_INFO    17    // char[1]+long[4]
  308. //#define    OFFS_DOC_COUNT    OFFS_DOC_INFO + WIDTH_DOC_INFO + 4    // +char[1]+long[5]
  309. //#define    OFFS_EXPORT_STR    OFFS_DOC_INFO + WIDTH_DOC_INFO
  310. //#define    OFFS_EXDATA_STR    OFFS_EXPORT_STR + 4/* +#(OFFS_EXPORT_STR) */
  311. //#define    OFFS_FORM_STR    OFFS_DOC_INFO+ 4/* +#(OFFS_EXPORT_STR) */ + 4/* +#(OFFS_EXDATA_STR) */
  312. //#define    OFFS_TYPE_STR        OFFS_FORM_STR + 4 /* +#(OFFS_FORM_STR) */
  313.  
  314.     offsetFInfo += WIDTH_DOC_INFO;
  315. //    For different formats.
  316.     if ( semaphore == 3 ) {
  317.         exportsize = GetLongLH( pFInfo+offsetFInfo );
  318.         offsetFInfo += sizeof(long) + exportsize;
  319.         exdatasize = GetLongLH( pFInfo+offsetFInfo );
  320.         offsetFInfo += sizeof(long) + exdatasize;
  321.         offsetFInfo += sizeof(long);
  322.     } else if ( semaphore == 5 ) {
  323.         // These 3 fields (export, exdata, (long)) are missing in new format.
  324.         // do nothing.
  325.     }
  326.  
  327.     // content-type (Can be Null string!)
  328.     sizeForm = GetLongLH( pFInfo+offsetFInfo );    
  329.     strForm = (unsigned char *) (pFInfo+offsetFInfo+sizeof(long));
  330. #ifdef DEBUG
  331.     Message("strForm: size=%ld¥n", sizeForm);
  332. #endif /* DEBUG */
  333.     if ( sizeForm < 0 || ALLOWANCE_LENGH < sizeForm )  { err = paramErr; goto out; }
  334.     offsetFInfo += sizeof(long) + sizeForm;
  335.  
  336.     // type (Can be Null string!)
  337.     sizeType = GetLongLH( pFInfo+offsetFInfo );    
  338.     strType = (unsigned char *) (pFInfo+offsetFInfo+sizeof(long));
  339. #ifdef DEBUG
  340.     Message("strType: size=%ld¥n", sizeType);
  341. #endif /* DEBUG */
  342.     if ( sizeType < 0 || ALLOWANCE_LENGH < sizeType )  { err = paramErr; goto out; }
  343.     offsetFInfo += sizeof(long) + sizeType;
  344.     
  345.     table->url = (unsigned long) strURL - (unsigned long) pHeap;
  346.     table->cache = (unsigned long) strCache - (unsigned long) pHeap;
  347.     table->form = (unsigned long) strForm - (unsigned long) pHeap;
  348.     table->type = (unsigned long) strType - (unsigned long) pHeap;
  349.     table->sizeurl = ( sizeURL < 1 ? 0 : sizeURL - 1 ) ;    // truncate the terminator '¥0'
  350.     table->sizecache = ( sizeCache < 1 ? 0 : sizeCache - 1 );
  351.     table->sizeform = ( sizeForm < 1 ? 0 : sizeForm - 1 );
  352.     table->sizetype = ( sizeType < 1 ? 0 : sizeType - 1 );
  353.     table->date1 = GetLongLH( pFInfo+OFFS_DATE1 );
  354.     table->date2 = GetLongLH( pFInfo+OFFS_DATE2 );
  355.     table->filesize = GetLongLH( pFInfo+OFFS_FILESIZE );
  356. //#define    OFFS_DATE1        OFFS_CACHE_INFO + 4
  357. //#define    OFFS_DATE2        OFFS_CACHE_INFO + 8
  358. //#define    OFFS_FILESIZE        OFFS_CACHE_INFO + 16
  359.  
  360. #ifdef DEBUG
  361.     Message("done¥n");
  362. #endif /* DEBUG */
  363.  
  364.   out:
  365.     HUnlock( theHndl );
  366.     return err;
  367. }
  368.  
  369.  
  370. static OSErr PrintRecord ( Handle theHndl, long index, IndexTableRecord *table )
  371. {
  372.     unsigned char    *pHeap;
  373.     
  374.     HLock( theHndl );
  375.     pHeap = (unsigned char *) *theHndl;
  376.  
  377. #ifdef DEBUG
  378.     Message("[%ld] cache=$%04X url=$%04X type=$%04X size=%ld¥n",
  379.         index, (short) table->cache,  (short) table->url, (short) table->type, table->filesize);
  380.     Message("Cache:%ld('%s')  ", table->sizecache, pHeap+table->cache);
  381.     Message("Type:%ld('%s')¥n", table->sizetype, pHeap+table->type);
  382.     Message("URL:%ld('%s')¥n", table->sizeurl, pHeap+table->url);
  383. #endif /* DEBUG */
  384.  
  385.     HUnlock( theHndl );
  386.     
  387.     return noErr;
  388. }
  389.  
  390.  
  391. #define TAB    "¥t"
  392. #define EOL    "¥r"
  393.  
  394. static OSErr InsertRecord ( Handle theHndl, Handle theHndl2, long index, IndexTableRecord *table )
  395. {
  396.     unsigned char    *pHeap;
  397.     Str255        text;
  398.  
  399.     HLock( theHndl );
  400.     pHeap = (unsigned char *) *theHndl;
  401.     
  402.     // for item 1 (some code '0')
  403.         AppendString( theHndl2, "0" TAB, 2 );
  404.     // for item 2 (date1)
  405.         NumToString(table->date1, text);
  406.         AppendString( theHndl2, (char *) &text[1], text[0] );
  407.         AppendString( theHndl2, TAB, 1 );
  408.     // for item 3 (date2)
  409.         NumToString(table->date2, text);
  410.         AppendString( theHndl2, (char *) &text[1], text[0] );
  411.         AppendString( theHndl2, TAB, 1 );
  412.     // for  item 4 ("cache12300")
  413.         AppendString( theHndl2, (char *) pHeap+table->cache, table->sizecache );
  414.         AppendString( theHndl2, TAB, 1 );
  415.     // for item 5 ("URL")
  416.         AppendString( theHndl2, (char *) pHeap+table->url, table->sizeurl );
  417.         AppendString( theHndl2, TAB, 1 );
  418.     // for item 6 (file/type)
  419.         AppendString( theHndl2, (char *) pHeap+table->type, table->sizetype );
  420.         AppendString( theHndl2, TAB, 1 );
  421.     // for item 7 (format ?)
  422.     //    AppendString( theHndl2, (char *) pHeap+table->form, table->sizeform );
  423.         AppendString( theHndl2, TAB, 1 );
  424.     // for item 8 (file size)
  425.         NumToString(table->filesize, text);
  426.         AppendString( theHndl2, (char *) &text[1], text[0] );
  427.     // for item 9 thru 10 (empty items)
  428.         AppendString( theHndl2, TAB TAB, 2 );
  429.     // for CR
  430.         AppendString( theHndl2, EOL, 1 );
  431.         
  432.     HUnlock( theHndl );
  433.  
  434.     return noErr;
  435. }
  436.  
  437. static OSErr InsertHeader ( Handle theHndl, Handle theHndl2 )
  438. {
  439.     Str255        text;
  440.  
  441.     // for header line
  442.         GetIndString( text, STRID_CACHE, STRIX_FORMAT );
  443.         AppendString( theHndl2, (char *) &text[1], text[0] );
  444.     // for CR
  445.         AppendString( theHndl2, EOL, 1 );
  446.         
  447.     return noErr;
  448. }
  449.  
  450. static OSErr AppendString ( Handle theHndl, const char *str, Size length )
  451. {
  452.     unsigned long    n;
  453.     OSErr        err;
  454.     
  455.     n = GetHandleSize( theHndl );
  456.     
  457.     SetHandleSize( theHndl, n+length );
  458.     if ( (err=MemError()) != noErr )
  459.         ErrorMessageMEM( err, true );
  460.  
  461.     BlockMove( str, (unsigned char *) *theHndl + n, length );
  462.  
  463.     return err;
  464. }
  465.  
  466. // end of program
  467.